#include "PlaceArcOfCircle.h"

#include "PadStackWidget.h"
#include "Gui.h"
#include "GraphicsArcOfCircle.h"

#include "LeIpc7351/PadStackElement.h"
#include "LeIpc7351/Primitives/ArcOfCircle.h"

#include "LeGraphicsView/LeGraphicsItem.h"
#include "LeGraphicsView/LeGraphicsItemLayer.h"
#include "LeGraphicsView/LeGraphicsScene.h"
#include "LeGraphicsView/LeGraphicsStyle.h"
#include "LeGraphicsView/LeGraphicsPalette.h"

#include <QDebug>
#include <QGraphicsSceneMouseEvent>
#include <QPainter>
#include <QRectF>

PlaceArcOfCircleTask::PlaceArcOfCircleTask(PadStackWidget *editor)
    : PadStackTask(editor)
    , LeGraphicsSceneEventFilter()
{
    setTile("Arc of circle");
    setDescription("Place an arc of circle");
    setIcon(Gui::icon("primitive-arc-of-circle"));
    setShortcut(QKeySequence("p,a,c"));
}


void PlaceArcOfCircleTask::start()
{
    m_primitive = new ArcOfCircle();
    m_primitive->setStartAngle(0.0);
    m_primitive->setSpanAngle(360.0);
    m_item = new GraphicsArcOfCircle(m_primitive);
    m_state = WaitForP1;
    scene()->setEventFilter(this);
    emit started(this);
}

void PlaceArcOfCircleTask::accept()
{
    Q_ASSERT(m_state == Finished);

    scene()->currentLayer()->removeFromLayer(m_item);
    delete m_item;
    m_item = nullptr;
    editor()->currentElement()->setPrimitive(m_primitive); // FIXME
    scene()->setEventFilter(nullptr);
    emit accepted(this);
}

void PlaceArcOfCircleTask::reject()
{
    if (m_state != WaitForP1)
    {
        scene()->currentLayer()->removeFromLayer(m_item);
    }
    delete m_item;
    m_item = nullptr;
    delete m_primitive;
    m_primitive = nullptr;
    scene()->setEventFilter(nullptr);
    emit rejected(this);
}

void PlaceArcOfCircleTask::drawBackground(QPainter *painter, const QRectF &rect)
{
    Q_UNUSED(painter)
    Q_UNUSED(rect)
}

void PlaceArcOfCircleTask::drawForeground(QPainter *painter, const QRectF &rect)
{
    Q_UNUSED(rect)

    if (m_item == nullptr)
        return;

    painter->setBrush(Qt::NoBrush);
    painter->setPen(QPen(scene()->graphicsPalette().color(LeGraphicsPalette::Highlight), 0));
    painter->drawLine(m_radiusLine);
    painter->setPen(QPen(scene()->graphicsPalette().color(LeGraphicsPalette::Highlight), 0, Qt::DotLine));
    QRectF bRect = m_item->boundingRect(); // FIXME: should be the rect in which the circle is inscribed
    // m_primitive->circumscribingRectangle()
    bRect.moveCenter(m_item->pos());
    painter->drawRect(bRect);
}

bool PlaceArcOfCircleTask::keyPressEvent(QKeyEvent *event)
{
    Q_UNUSED(event)
    return true;
}

bool PlaceArcOfCircleTask::keyReleaseEvent(QKeyEvent *event)
{
    Q_UNUSED(event)
    return true;
}

bool PlaceArcOfCircleTask::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
    Q_UNUSED(event)
    return true;
}

bool PlaceArcOfCircleTask::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
    if (m_state == WaitForP1)
    {
        m_radiusLine.setP1(event->scenePos());
    }
    else if (m_state == WaitForP2)
    {
        m_radiusLine.setP2(event->scenePos());
        const qreal radius = qMax(qAbs(m_radiusLine.dx()),
                                  qAbs(m_radiusLine.dy()));
        m_radiusLine.setLength(radius);
        m_primitive->setDiameter(radius*2.0);
    }
    else if (m_state == WaitForP3)
    {
        m_radiusLine.setP2(event->scenePos());
        m_radiusLine.setLength(m_primitive->diameter()/2.0);
        m_primitive->setStartAngle(-m_radiusLine.angle());

    }
    else if (m_state == WaitForP4)
    {
        m_radiusLine.setP2(event->scenePos());
        m_radiusLine.setLength(m_primitive->diameter()/2.0);
        m_primitive->setSpanAngle((720-m_radiusLine.angle())-m_primitive->startAngle());
    }
    return true;
}

bool PlaceArcOfCircleTask::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
    if (m_state == WaitForP1)
    {
        m_primitive->setPosition(event->scenePos());
        scene()->currentLayer()->addToLayer(m_item);
        m_radiusLine.setP1(event->scenePos());
        m_state = WaitForP2;
        mouseMoveEvent(event);
        return true;
    }
    else if (m_state == WaitForP2)
    {
        m_state = WaitForP3;
        m_primitive->setSpanAngle(180.0);
        mouseMoveEvent(event);
    }
    else if (m_state == WaitForP3)
    {
        m_state = WaitForP4;
        mouseMoveEvent(event);
    }
    else if (m_state == WaitForP4)
    {
        m_state = Finished;
        accept();
    }
    return true;
}

bool PlaceArcOfCircleTask::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
{
    Q_UNUSED(event)
    return true;
}
